package cn.test.excel.jxsl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

import cn.hutool.core.convert.NumberChineseFormatter;
import cn.hutool.core.util.StrUtil;
import cn.test.util.BigDecimalUtil;
import cn.test.util.DateUtil;
import cn.test.util.NumberUtil;
import org.apache.commons.lang3.StringUtils;

/***JXLS模板填充自定义函数*/
public class JXLSFunction {

    public static final String FUNCTION_NAME = "Function";

    private static final JXLSFunction jxlsFunction = new JXLSFunction();

    private JXLSFunction() {
    }

    public static JXLSFunction getInstance() {
        return jxlsFunction;
    }

    public String doNothing(Object value) {
        if (Objects.isNull(value)) {
            return "";
        }
        return String.valueOf(value);
    }

    public String dateFormat(Object value) {
        if (Objects.isNull(value)) {
            return "";
        }
        LocalDate resultDate = DateUtil.toLocalDate(value);
        if (Objects.isNull(resultDate)) {
            return "";
        }
        return resultDate.format(DateUtil.DEFAULT_FORMAT_PATTERN);
    }

    public String dateFormat(Object value, String formatter) {
        if (Objects.isNull(value)) {
            return "";
        }
        DateTimeFormatter dateTimeFormatter = DateUtil.DEFAULT_FORMAT_PATTERN;
        if (StringUtils.isNotBlank(formatter)) {
            dateTimeFormatter = DateTimeFormatter.ofPattern(formatter);
        }
        LocalDate resultDate = DateUtil.toLocalDate(value);
        if (Objects.isNull(resultDate)) {
            return "";
        }
        return resultDate.format(dateTimeFormatter);
    }

    public Integer daysBetween(Object value1, Object value2) {
        if (Objects.isNull(value1) || Objects.isNull(value2)) {
            return null;
        }
        LocalDate startLocalDate = DateUtil.toLocalDate(value1);
        LocalDate endLocalDate = DateUtil.toLocalDate(value2);
        return Math.toIntExact(startLocalDate.toEpochDay() - endLocalDate.toEpochDay());
    }

    public static Object nvl(Object value1, Object value2) {
        if (Objects.isNull(value1) || StrUtil.isEmpty(value1.toString())) {
            return value2;
        } else {
            return value1;
        }
    }

    public static String divide(Object value1, Object value2) {
        if (Objects.isNull(value1) || Objects.isNull(value2)) {
            return "0";
        }
        BigDecimal dividend = new BigDecimal(value1.toString());
        BigDecimal divisor = new BigDecimal(value2.toString());
        if (BigDecimal.ZERO.compareTo(divisor) == 0) {
            return "0";
        }
        return dividend.divide(divisor, 100, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    public static String divide(Object value1, Object value2, Object value3) {
        if (Objects.isNull(value1) || Objects.isNull(value2)) {
            return "0";
        }
        int scale = 100;
        if (Objects.nonNull(value3)) {
            scale = (int) value3;
        }
        BigDecimal dividend = new BigDecimal(value1.toString());
        BigDecimal divisor = new BigDecimal(value2.toString());
        if (BigDecimal.ZERO.compareTo(divisor) == 0) {
            return "0";
        }
        return dividend.divide(divisor, scale, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    public String numNegate(Object value) {
        if (Objects.isNull(value)) {
            return "0";
        }
        return new BigDecimal(value.toString()).negate().toPlainString();
    }

    public String numFormat(Object value) {
        if (Objects.isNull(value)) {
            return "0";
        }
        return NumberUtil.formatNum(new BigDecimal(value.toString()));
    }

    public String numFormat(Object value, int pointNum) {
        if (Objects.isNull(value)) {
            return "0";
        }
        return NumberUtil.formatNum(new BigDecimal(value.toString()), pointNum);
    }

    public String numFormat(Object value, int pointNum, int tag) {
        if (Objects.isNull(value)) {
            return "0";
        }
        BigDecimal numTag = new BigDecimal(String.valueOf(tag));
        return NumberUtil.formatNum(BigDecimalUtil.multiply(new BigDecimal(value.toString()), numTag), pointNum);
    }

    public String thdNum(Object value) {
        if (Objects.isNull(value)) {
            return "0";
        }
        return NumberUtil.formatThdByPara(new BigDecimal(value.toString()));
    }

    public String thdNum(Object value, int pointNum) {
        if (Objects.isNull(value)) {
            return "0";
        }
        return NumberUtil.formatThd(new BigDecimal(value.toString()), pointNum);
    }

    public String thdNum(Object value, int pointNum, int tag) {
        if (Objects.isNull(value)) {
            return "0";
        }
        BigDecimal numTag = new BigDecimal(String.valueOf(tag));
        return NumberUtil.formatThd(BigDecimalUtil.multiply(new BigDecimal(value.toString()), numTag), pointNum);
    }

    public String chineseMoney(Object value) {
        if (Objects.isNull(value)) {
            return "";
        }
        return NumberChineseFormatter.format(Double.parseDouble(value.toString()), true, true);
    }

    public String percent(Object value) {
        if (Objects.isNull(value)) {
            return "";
        }
        BigDecimal numValue = new BigDecimal(value.toString());
        int pointNum = numValue.scale();
        return NumberUtil.percentFormat(numValue, pointNum);
    }

    public String percent(Object value, int pointNum) {
        if (Objects.isNull(value)) {
            return "";
        }
        return NumberUtil.percentFormat(new BigDecimal(value.toString()), pointNum);
    }

    public String percentWithoutZero(Object value, int pointNum) {
        if (Objects.isNull(value)) {
            return "";
        }
        BigDecimal bigDecimal = new BigDecimal(value.toString());
        if (bigDecimal.compareTo(BigDecimal.ZERO) == 0) {
            return "";
        }
        return NumberUtil.percentFormat(bigDecimal, pointNum);
    }

    public String thousandth(Object value) {
        if (Objects.isNull(value)) {
            return "";
        }
        BigDecimal numValue = new BigDecimal(value.toString());
        int pointNum = numValue.scale();
        return NumberUtil.thousandthFormat(new BigDecimal(value.toString()), pointNum);
    }

    public String thousandth(Object value, int pointNum) {
        if (Objects.isNull(value)) {
            return "";
        }
        return NumberUtil.thousandthFormat(new BigDecimal(value.toString()), pointNum);
    }
}
